home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 009a / snpd0493.zip / BMHISRCH.C < prev    next >
C/C++ Source or Header  |  1993-04-05  |  3KB  |  92 lines

  1. /*
  2. **  Case-Insensitive Boyer-Moore-Horspool pattern match
  3. **
  4. **  Public Domain version by Thad Smith 7/21/1992,
  5. **  based on a 7/92 public domain BMH version by Raymond Gardner.
  6. **
  7. **  This program is written in ANSI C and inherits the compilers
  8. **  ability (or lack thereof) to support non-"C" locales by use of
  9. **  toupper() and tolower() to perform case conversions.
  10. **  Limitation: pattern length + string length must be less than 32767.
  11. */
  12.  
  13. #include <limits.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17.  
  18. typedef unsigned char uchar;
  19.  
  20. #define LARGE 32767             /* flag for last character match    */
  21.  
  22. static int patlen;              /* # chars in pattern               */
  23. static int skip[UCHAR_MAX+1];   /* skip-ahead count for test chars  */
  24. static int skip2;               /* skip-ahead after non-match with
  25.                                 ** matching final character         */
  26. static uchar *pat = NULL;       /* uppercase copy of pattern        */
  27.  
  28. /*
  29. ** bmhi_init() is called prior to bmhi_search() to calculate the
  30. ** skip array for the given pattern.
  31. ** Error: exit(1) is called if no memory is available.
  32. */
  33.  
  34. void bmhi_init(const char *pattern)
  35. {
  36.       int i, lastpatchar;
  37.       patlen = strlen(pattern);
  38.  
  39.       /* Make uppercase copy of pattern */
  40.  
  41.       pat = realloc ((void*)pat, patlen);
  42.       if (!pat)
  43.             exit(1);
  44.       for (i=0; i < patlen; i++)
  45.             pat[i] = toupper(pattern[i]);
  46.  
  47.       /* initialize skip array */
  48.  
  49.       for ( i = 0; i < UCHAR_MAX; ++i )
  50.             skip[i] = patlen;
  51.       for ( i = 0; i < patlen - 1; ++i )
  52.       {
  53.             skip[        pat[i] ] = patlen - i - 1;
  54.             skip[tolower(pat[i])] = patlen - i - 1;
  55.       }
  56.       lastpatchar = pat[patlen - 1];
  57.       skip[        lastpatchar ] = LARGE;
  58.       skip[tolower(lastpatchar)] = LARGE;
  59.       skip2 = patlen;                     /* Horspool's fixed second shift */
  60.       for (i = 0; i < patlen - 1; ++i)
  61.       {
  62.             if ( pat[i] == lastpatchar )
  63.                   skip2 = patlen - i - 1;
  64.       }
  65. }
  66.  
  67. char *bmhi_search(const char *string, const int stringlen)
  68. {
  69.       int i, j;
  70.       char *s;
  71.  
  72.       i = patlen - 1 - stringlen;
  73.       if (i >= 0)
  74.             return NULL;
  75.       string += stringlen;
  76.       for ( ;; )
  77.       {
  78.             while ( (i += skip[((uchar *)string)[i]]) < 0 )
  79.                   ;                           /* mighty fast inner loop */
  80.             if (i < (LARGE - stringlen))
  81.                   return NULL;
  82.             i -= LARGE;
  83.             j = patlen - 1;
  84.             s = (char *)string + (i - j);
  85.             while ( --j >= 0 && toupper(s[j]) == pat[j] )
  86.                   ;
  87.             if ( j >= 0 )
  88.                   i += skip2;
  89.             else  return s;
  90.       }
  91. }
  92.